/**
 * AI智能体插件工具类库
 * 统一管理常用的工具方法，提高代码复用性和可维护性
 */

import { 
  MESSAGE_TYPES, 
  REGEX_PATTERNS, 
  ENV_VARS, 
  ERROR_CODES, 
  MOCK_CONFIG,
  DEBUG,
  MESSAGE_CONTENT
} from '../common/constants.js';

// ==================== 类型检查工具 ====================

/**
 * 判断值是否为空（null、undefined、空字符串、空数组、空对象）
 * @param {*} value 要检查的值
 * @returns {boolean} 是否为空
 */
export const isEmpty = (value) => {
  switch (typeof value) {
    case 'undefined':
      return true;
    case 'string':
      if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true;
      break;
    case 'boolean':
      if (!value) return true;
      break;
    case 'number':
      if (value === 0 || isNaN(value)) return true;
      break;
    case 'object':
      if (value === null) return true;
      if (Array.isArray(value) && value.length === 0) return true;
      for (const i in value) {
        return false;
      }
      return true;
    default:
      return false;
  }
  return false;
};

/**
 * 判断值是否为函数
 * @param {*} value 要检查的值
 * @returns {boolean} 是否为函数
 */
export const isFunction = (value) => {
  return typeof value === 'function';
};

/**
 * 判断值是否为对象（排除null和数组）
 * @param {*} value 要检查的值
 * @returns {boolean} 是否为对象
 */
export const isObject = (value) => {
  return value !== null && typeof value === 'object' && !Array.isArray(value);
};

/**
 * 判断值是否为Promise
 * @param {*} value 要检查的值
 * @returns {boolean} 是否为Promise
 */
export const isPromise = (value) => {
  return value && typeof value.then === 'function';
};

/**
 * 判断字符串是否为有效的JSON
 * @param {string} str 要检查的字符串
 * @returns {boolean} 是否为有效JSON
 */
export const isJsonString = (str) => {
  // 先快速检查是否为空字符串
  if (typeof str !== "string") {
    return false;
  }

  // 去掉两端的空白字符
  str = str.trim();

  // 判断是否是空字符串
  if (str === "") {
    return false;
  }

  // 检查是否是对象或数组的基本结构
  if (
    (str.startsWith("{") && str.endsWith("}")) ||
    (str.startsWith("[") && str.endsWith("]"))
  ) {
    try {
      // 尝试解析
      JSON.parse(str);
      return true;
    } catch {
      // 如果解析失败，返回 false
      return false;
    }
  }

  return false;
};

/**
 * 判断是否为有效的URL
 * @param {string} url 要检查的URL
 * @returns {boolean} 是否为有效URL
 */
export const isValidUrl = (url) => {
  return typeof url === 'string' && REGEX_PATTERNS.URL.test(url);
};

// ==================== 环境检查工具 ====================

/**
 * 获取当前Mock模式状态
 * @returns {boolean} 是否为Mock模式
 */
export const isMockMode = () => {
  const mockVar = process.env[ENV_VARS.MOCK_MODE];
  return mockVar === 'true' || mockVar === true;
};

/**
 * 获取当前运行平台
 * @returns {string} 平台标识
 */
export const getCurrentPlatform = () => {
  // 为了通过 ESLint 静态分析，实际编译时会被条件编译 return 覆盖
  let platform = 'unknown';
  // #ifdef H5
  platform = 'h5';
  // #endif
  // #ifdef MP-WEIXIN
  platform = 'mp-weixin';
  // #endif
  // #ifdef MP-ALIPAY
  platform = 'mp-alipay';
  // #endif
  // #ifdef APP-PLUS
  platform = 'app-plus';
  // #endif
  return platform;
};

/**
 * 判断是否为小程序环境
 * @returns {boolean} 是否为小程序
 */
export const isMiniProgram = () => {
  const platform = getCurrentPlatform();
  return platform.startsWith('mp-');
};

/**
 * 判断是否为大屏设备
 * @param {number} threshold 大屏判断阈值，默认700px
 * @returns {boolean} 是否为大屏设备
 */
export const isWideScreen = (threshold = 700) => {
  try {
    const systemInfo = uni.getSystemInfoSync();
    return systemInfo.windowWidth >= threshold;
  } catch {
    return false;
  }
};

// ==================== 数据处理工具 ====================

/**
 * 深拷贝对象
 * @param {*} obj 要拷贝的对象
 * @returns {*} 深拷贝结果
 */
export const deepClone = (obj) => {
  if (obj === null || typeof obj !== 'object') return obj;
  if (obj instanceof Date) return new Date(obj.getTime());
  if (obj instanceof Array) return obj.map(item => deepClone(item));
  if (typeof obj === 'object') {
    const copy = {};
    Object.keys(obj).forEach(key => {
      copy[key] = deepClone(obj[key]);
    });
    return copy;
  }
  return obj;
};

/**
 * 合并对象（深度合并）
 * @param {object} target 目标对象
 * @param {...object} sources 源对象
 * @returns {object} 合并后的对象
 */
export const deepMerge = (target, ...sources) => {
  if (!sources.length) return target;
  const source = sources.shift();
  
  if (isObject(target) && isObject(source)) {
    for (const key in source) {
      if (isObject(source[key])) {
        if (!target[key]) Object.assign(target, { [key]: {} });
        deepMerge(target[key], source[key]);
      } else {
        Object.assign(target, { [key]: source[key] });
      }
    }
  }
  
  return deepMerge(target, ...sources);
};

/**
 * 安全的JSON解析
 * @param {string} jsonString JSON字符串
 * @param {*} defaultValue 解析失败时的默认值
 * @returns {*} 解析结果
 */
export const safeJsonParse = (jsonString, defaultValue = null) => {
  try {
    return JSON.parse(jsonString);
  } catch {
    return defaultValue;
  }
};

/**
 * 数组去重
 * @param {Array} array 要去重的数组
 * @param {string|Function} key 去重依据的键名或函数
 * @returns {Array} 去重后的数组
 */
export const uniqueArray = (array, key) => {
  if (!Array.isArray(array)) return [];
  
  if (!key) {
    return [...new Set(array)];
  }
  
  const seen = new Set();
  return array.filter(item => {
    const value = typeof key === 'function' ? key(item) : item[key];
    if (seen.has(value)) {
      return false;
    }
    seen.add(value);
    return true;
  });
};

// ==================== 字符串处理工具 ====================

/**
 * 生成唯一ID
 * @param {string} prefix 前缀
 * @returns {string} 唯一ID
 */
export const generateId = (prefix = 'id') => {
  return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
};

/**
 * 截断字符串
 * @param {string} str 要截断的字符串
 * @param {number} length 最大长度
 * @param {string} ellipsis 省略符号
 * @returns {string} 截断后的字符串
 */
export const truncateString = (str, length = 100, ellipsis = '...') => {
  if (!str || typeof str !== 'string') return '';
  if (str.length <= length) return str;
  return str.substring(0, length - ellipsis.length) + ellipsis;
};

/**
 * 格式化文件大小
 * @param {number} bytes 字节数
 * @param {number} decimals 小数位数
 * @returns {string} 格式化后的大小
 */
export const formatFileSize = (bytes, decimals = 2) => {
  if (bytes === 0) return '0 B';
  
  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
  
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
};

/**
 * 转换为驼峰命名
 * @param {string} str 要转换的字符串
 * @returns {string} 驼峰命名字符串
 */
export const toCamelCase = (str) => {
  return str.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
};

/**
 * 转换为中划线命名
 * @param {string} str 要转换的字符串
 * @returns {string} 中划线命名字符串
 */
export const toKebabCase = (str) => {
  return str.replace(/([A-Z])/g, '-$1').toLowerCase();
};

// ==================== 时间处理工具 ====================

/**
 * 获取当前时间字符串
 * @param {string} format 时间格式，默认'YYYY-MM-DD HH:mm:ss'
 * @returns {string} 格式化后的时间字符串
 */
export const getCurrentDateTime = (format = 'YYYY-MM-DD HH:mm:ss') => {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are zero based
  const day = String(now.getDate()).padStart(2, '0');
  const hours = String(now.getHours()).padStart(2, '0');
  const minutes = String(now.getMinutes()).padStart(2, '0');
  const seconds = String(now.getSeconds()).padStart(2, '0');

  return format
    .replace('YYYY', year)
    .replace('MM', month)
    .replace('DD', day)
    .replace('HH', hours)
    .replace('mm', minutes)
    .replace('ss', seconds);
};

/**
 * 格式化相对时间
 * @param {Date|string|number} date 日期
 * @returns {string} 相对时间字符串
 */
export const formatRelativeTime = (date) => {
  const now = new Date();
  const targetDate = new Date(date);
  const diffMs = now - targetDate;
  const diffSec = Math.floor(diffMs / 1000);
  const diffMin = Math.floor(diffSec / 60);
  const diffHour = Math.floor(diffMin / 60);
  const diffDay = Math.floor(diffHour / 24);
  
  if (diffSec < 60) return '刚刚';
  if (diffMin < 60) return `${diffMin}分钟前`;
  if (diffHour < 24) return `${diffHour}小时前`;
  if (diffDay < 7) return `${diffDay}天前`;
  
  return targetDate.toLocaleDateString();
};

/**
 * 防抖函数
 * @param {Function} fn 要防抖的函数
 * @param {number} delay 延迟时间（毫秒）
 * @returns {Function} 防抖后的函数
 */
export const debounce = (fn, delay) => {
  let timeout = null;
  return function() {
    let arg = arguments;
    clearTimeout(timeout);
    timeout = setTimeout(() => {
      fn.apply(this, arg);
    }, delay);
  };
};

/**
 * 节流函数
 * @param {Function} fn 要节流的函数
 * @param {number} delay 延迟时间（毫秒）
 * @returns {Function} 节流后的函数
 */
export const throttle = (fn, delay) => {
  let prev = Date.now();
  return function() {
    let arg = arguments;
    let now = Date.now();
    if (now - prev > delay) {
      fn.apply(this, arg);
      prev = Date.now();
    }
  };
};

// ==================== 存储工具 ====================

/**
 * 安全的本地存储设置
 * @param {string} key 存储键
 * @param {*} value 存储值
 * @returns {boolean} 是否设置成功
 */
export const setStorage = (key, value) => {
  try {
    const serializedValue = JSON.stringify(value);
    uni.setStorageSync(key, serializedValue);
    return true;
  } catch (error) {
    console.error('设置本地存储失败:', error);
    return false;
  }
};

/**
 * 安全的本地存储获取
 * @param {string} key 存储键
 * @param {*} defaultValue 默认值
 * @returns {*} 存储的值或默认值
 */
export const getStorage = (key, defaultValue = null) => {
  try {
    const serializedValue = uni.getStorageSync(key);
    return serializedValue ? JSON.parse(serializedValue) : defaultValue;
  } catch (error) {
    console.error('获取本地存储失败:', error);
    return defaultValue;
  }
};

/**
 * 移除本地存储
 * @param {string} key 存储键
 * @returns {boolean} 是否移除成功
 */
export const removeStorage = (key) => {
  try {
    uni.removeStorageSync(key);
    return true;
  } catch (error) {
    console.error('移除本地存储失败:', error);
    return false;
  }
};

/**
 * 清空本地存储
 * @returns {boolean} 是否清空成功
 */
export const clearStorage = () => {
  try {
    uni.clearStorageSync();
    return true;
  } catch (error) {
    console.error('清空本地存储失败:', error);
    return false;
  }
};

// ==================== 数组和数据处理工具 ====================

/**
 * 数组按指定键分组
 * @param {Array} arr 要分组的数组
 * @param {string} key 分组依据的键名
 * @returns {Object} 分组后的对象
 */
export const Group = (arr = [], key) => {
  return key ?
    arr.reduce(
      (t, v) => (!t[v[key]] && (t[v[key]] = []), t[v[key]].push(v), t), {}
    ) : {};
};

/**
 * 显示Toast提示
 * @param {string} message 提示消息
 * @param {object} options 提示选项
 */
export const showToast = (message, options = {}) => {
  uni.showToast({
    icon: "none",
    title: message,
    ...options
  });
};

/**
 * 移除Base64前缀
 * @param {string} data Base64数据
 * @returns {string|null} 移除前缀后的数据
 */
export const removeBase64Prefix = (data) => {
  if (!data || typeof data != "string") {
    return null;
  }
  return data.slice(data.indexOf("base64,") + 7);
};

// ==================== Mock数据工具 ====================

/**
 * 生成Mock消息回复
 * @param {string} message 用户输入消息
 * @param {object} options 生成选项
 * @returns {object} Mock回复数据
 */
export const generateMockResponse = (message, options = {}) => {
  const { deepThink = false, webSearch = false } = options;
  
  let responses = [];
  let delay = MOCK_CONFIG.DELAYS.NORMAL;
  
  if (deepThink) {
    responses = [...MOCK_CONFIG.RESPONSES.DEEP_THINK];
    delay = MOCK_CONFIG.DELAYS.DEEP_THINK;
  } else if (webSearch) {
    responses = [...MOCK_CONFIG.RESPONSES.WEB_SEARCH];
    delay = MOCK_CONFIG.DELAYS.WEB_SEARCH;
  } else {
    responses = [...MOCK_CONFIG.RESPONSES.DEFAULT];
  }
  
  // 根据消息内容智能选择回复
  if (message.includes('图表') || message.includes('chart')) {
    responses.push('📊 这里是一个示例图表，展示相关数据分析结果。');
  } else if (message.includes('商品') || message.includes('产品')) {
    responses.push('🛍️ 为您推荐相关商品信息。');
  } else if (message.includes('活动') || message.includes('优惠')) {
    responses.push('🎉 当前有以下优惠活动供您参考。');
  }
  
  return {
    messages: responses.map(text => `[TEXT]${text}`),
    delay,
    totalCount: responses.length
  };
};

/**
 * 生成Mock图表数据
 * @param {string} chartType 图表类型
 * @returns {object} Mock图表数据
 */
export const generateMockChartData = (chartType = 'bar') => {
  const baseData = MOCK_CONFIG.GENERATORS.CHART_SAMPLE;
  
  switch (chartType) {
    case 'line':
      return {
        ...baseData,
        type: 'line',
        data: {
          ...baseData.data,
          datasets: [{
            ...baseData.data.datasets[0],
            fill: false,
            tension: 0.1
          }]
        }
      };
    case 'pie':
      return {
        type: 'pie',
        data: {
          labels: ['类别A', '类别B', '类别C'],
          datasets: [{
            data: [30, 40, 30],
            backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56']
          }]
        }
      };
    default:
      return baseData;
  }
};

// ==================== 错误处理工具 ====================

/**
 * 创建标准化错误对象
 * @param {string} code 错误码
 * @param {string} message 错误消息
 * @param {*} data 附加数据
 * @returns {object} 标准化错误对象
 */
export const createError = (code, message, data = null) => {
  return {
    code,
    message,
    data,
    timestamp: Date.now(),
    isError: true
  };
};

/**
 * 错误处理包装器
 * @param {Function} asyncFunc 异步函数
 * @param {string} errorMessage 错误消息前缀
 * @returns {Function} 包装后的函数
 */
export const withErrorHandler = (asyncFunc, errorMessage = '操作失败') => {
  return async (...args) => {
    try {
      return await asyncFunc(...args);
    } catch (error) {
      console.error(`${errorMessage}:`, error);
      return createError(
        ERROR_CODES.API_ERROR,
        `${errorMessage}: ${error.message || error}`,
        error
      );
    }
  };
};

// ==================== 调试工具 ====================

/**
 * 统一的日志输出
 * @param {string} level 日志级别
 * @param {string} message 消息
 * @param {*} data 附加数据
 */
export const log = (level, message, data = null) => {
  const prefix = DEBUG.PREFIXES[level.toUpperCase()] || '';
  const timestamp = getCurrentDateTime('HH:mm:ss');
  
  const fullMessage = `${prefix} [${timestamp}] ${message}`;
  
  switch (level.toLowerCase()) {
    case 'error':
      console.error(fullMessage, data);
      break;
    case 'warn':
      console.warn(fullMessage, data);
      break;
    case 'info':
      console.info(fullMessage, data);
      break;
    case 'debug':
    default:
      console.log(fullMessage, data);
      break;
  }
};

/**
 * 性能监控包装器
 * @param {Function} func 要监控的函数
 * @param {string} name 函数名称
 * @returns {Function} 包装后的函数
 */
export const withPerformanceMonitor = (func, name) => {
  return async (...args) => {
    const startTime = performance.now();
    
    try {
      const result = await func(...args);
      const endTime = performance.now();
      const duration = endTime - startTime;
      
      if (duration > 100) { // 超过100ms记录警告
        log('warn', `${name} 执行时间较长`, { duration: `${duration.toFixed(2)}ms` });
      } else {
        log('debug', `${name} 执行完成`, { duration: `${duration.toFixed(2)}ms` });
      }
      
      return result;
    } catch (error) {
      const endTime = performance.now();
      const duration = endTime - startTime;
      
      log('error', `${name} 执行失败`, { 
        duration: `${duration.toFixed(2)}ms`, 
        error: error.message 
      });
      
      throw error;
    }
  };
};

// ==================== 消息处理工具 ====================

/**
 * 格式化消息数据
 * @param {object} rawMessage 原始消息数据
 * @returns {object} 格式化后的消息数据
 */
export const formatMessage = (rawMessage) => {
  return {
    key: rawMessage.serialNo || generateId('msg'),
    createTime: rawMessage.createTime || getCurrentDateTime(),
    role: rawMessage.type === MESSAGE_TYPES.USER ? 'user' : 
          rawMessage.type === MESSAGE_TYPES.AI ? 'ai' : 'slot',
    content: rawMessage.content || '',
    contentType: rawMessage.contentType || 'text',
    contentAppendData: rawMessage.contentAppendData || null,
    deepThinkStatus: rawMessage.deepThinkStatus || false,
    deepThinkContent: rawMessage.deepThinkContent || '',
    deepThinkTime: rawMessage.deepThinkTime || 0,
    messageId: rawMessage.messageId || generateId('msg'),
    timestamp: rawMessage.timestamp || Date.now(),
    ...rawMessage
  };
};

/**
 * 验证消息数据
 * @param {object} message 消息数据
 * @returns {object} 验证结果
 */
export const validateMessage = (message) => {
  const errors = [];
  
  if (!message) {
    errors.push('消息数据不能为空');
  } else {
    if (!message.content && message.type !== MESSAGE_TYPES.SLOT) {
      errors.push('消息内容不能为空');
    }
    
    if (!Object.values(MESSAGE_TYPES).includes(message.type)) {
      errors.push('无效的消息类型');
    }
    
    if (message.content && message.content.length > MESSAGE_CONTENT.MAX_LENGTH) {
      errors.push(`消息内容超出最大长度限制（${MESSAGE_CONTENT.MAX_LENGTH}字符）`);
    }
  }
  
  return {
    isValid: errors.length === 0,
    errors
  };
};

// ==================== 导出所有工具方法 ====================
export default {
  // 类型检查
  isEmpty,
  isFunction,
  isObject,
  isPromise,
  isJsonString,
  isValidUrl,
  
  // 环境检查
  isMockMode,
  getCurrentPlatform,
  isMiniProgram,
  isWideScreen,
  
  // 数据处理
  deepClone,
  deepMerge,
  safeJsonParse,
  uniqueArray,
  Group,
  
  // 字符串处理
  generateId,
  truncateString,
  formatFileSize,
  toCamelCase,
  toKebabCase,
  
  // 时间处理
  getCurrentDateTime,
  formatRelativeTime,
  debounce,
  throttle,
  
  // 存储工具
  setStorage,
  getStorage,
  removeStorage,
  clearStorage,
  
  // UI工具
  showToast,
  removeBase64Prefix,
  
  // Mock数据
  generateMockResponse,
  generateMockChartData,
  
  // 错误处理
  createError,
  withErrorHandler,
  
  // 调试工具
  log,
  withPerformanceMonitor,
  
  // 消息处理
  formatMessage,
  validateMessage
}; 